home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / Xconq 7.0d16 / Xconq 7.0d16 src / mac / maclist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-10  |  19.0 KB  |  787 lines  |  [TEXT/KAHL]

  1. /* Copyright (c) 1992, 1993  Stanley T. Shebs. */
  2. /* This program may be used, copied, modified, and redistributed freely */
  3. /* for noncommercial purposes, so long as this notice remains intact. */
  4.  
  5. /* Unit lists for the Mac interface. */
  6.  
  7. #include "conq.h"
  8. #include "mac.h"
  9.  
  10. /* (should be adjusted for expected range of values sometimes) */
  11.  
  12. int curactcolw = 10;
  13. int imagecolw = 20;
  14. int namecolw = 100;
  15. int typecolw = 70;
  16. int sidecolw = 70;
  17. int hpcolw = 40;
  18. int acpcolw = 60;
  19. int poscolw = 60;
  20. int supcolw = 40;
  21. int notecolw = 50;
  22.  
  23. int maxlistwidth;
  24.  
  25. int listtoph = 20;
  26. int entryspacing;
  27. int smallentryspacing = 18;
  28. int largeentryspacing = 34;
  29.  
  30. int fixedfieldwidth;
  31.  
  32. int listnum = 1;
  33.  
  34. int lastlisth = -1, lastlistv = -1;
  35.  
  36. create_list()
  37. {
  38.     int i, numvisunits, h, v;
  39.     List *list = (List *) xmalloc(sizeof(List));
  40.     Rect hscrollrect, vscrollrect;
  41.  
  42.     maxlistwidth = 0;
  43.     maxlistwidth += curactcolw;
  44.     maxlistwidth += imagecolw;
  45.     maxlistwidth += namecolw;
  46.     fixedfieldwidth = maxlistwidth;
  47.     maxlistwidth += typecolw;
  48.     maxlistwidth += sidecolw;
  49.     maxlistwidth += hpcolw;
  50.     maxlistwidth += acpcolw;
  51.     maxlistwidth += poscolw;
  52.     maxlistwidth += nummtypes * supcolw;
  53.     maxlistwidth += notecolw;
  54.  
  55.     DGprintf("Creating a list\n");
  56.     list->sides == -1L;  /* lists every side and indeps too */
  57.     for (i = 0; i < MAXSORTKEYS; ++i) {
  58.         list->sortkeys[i] = bynothing;
  59.     }
  60.     list->sortkeys[0] = byside;
  61.     list->mainsortmi = miViewBySide;
  62.     list->listglimpsed = FALSE;
  63.     init_list_contents(list);
  64.     organize_list_contents(list);
  65.     list->next = listlist;
  66.     listlist = list;
  67.     /* Make a window for the list, give it scrollbars. */
  68.     list->window = GetNewWindow(wList, nil, (WindowPtr) -1L);
  69.     stagger_window(list->window, &lastlisth, &lastlistv);
  70.     ShowWindow(list->window);
  71.     SetPort(list->window);
  72.     hscrollrect = list->window->portRect;
  73.     hscrollrect.top = hscrollrect.bottom - sbarwid;
  74.     hscrollrect.bottom += 1;
  75.     hscrollrect.left += (curactcolw + imagecolw + namecolw) + 1;
  76.     hscrollrect.right -= sbarwid - 1;
  77.     list->hscrollbar = NewControl(list->window, &hscrollrect, "\p", TRUE,
  78.                                    0, 0, 300, scrollBarProc, 0L);
  79.     vscrollrect = list->window->portRect;
  80.     vscrollrect.top -= 1;
  81.     vscrollrect.bottom -= sbarwid - 1;
  82.     vscrollrect.left = vscrollrect.right - sbarwid;
  83.     vscrollrect.right += 1;
  84.     numvisunits = (vscrollrect.bottom - vscrollrect.top) / smallentryspacing;
  85.     list->vscrollbar = NewControl(list->window, &vscrollrect, "\p", TRUE,
  86.                                    0, 0, max(0, list->numunits - numvisunits), scrollBarProc, 0L);
  87.     set_list_scrollbar(list);
  88.     list->firstvisible = 0;
  89.     sprintf(spbuf, "List %d", listnum++);
  90.     add_window_menu_item(spbuf, list->window);
  91. }
  92.  
  93. /* Make the list be empty. */
  94.  
  95. init_list_contents(list)
  96. List *list;
  97. {
  98.     int i;
  99.  
  100.     list->contents = make_unit_vector(500);
  101.     list->numunits = 0;
  102. }
  103.  
  104. /* This takes the list and fills in the items it is to display. */
  105.  
  106. organize_list_contents(list)
  107. List *list;
  108. {
  109.     Side *side2;
  110.     Unit *unit;
  111.  
  112.     /* Build up the array of units for this list. */
  113.     list->numunits = 0;
  114.     clear_unit_vector(list->contents);
  115.     /* We always see our own units. */
  116.     for_all_side_units(dside, unit) {
  117.         add_unit_to_list(list, unit);
  118.     }
  119.     for_all_sides(side2) {
  120.         if (dside != side2) {
  121.             for_all_side_units(side2, unit) {
  122.                 if (side_sees_image(dside, unit)) {
  123.                     add_unit_to_list(list, unit);
  124.                 }
  125.             }
  126.         }
  127.     }
  128.     for_all_side_units(indepside, unit) {
  129.         if (side_sees_image(dside, unit)) {
  130.             add_unit_to_list(list, unit);
  131.         }
  132.     }
  133.     /* Now sort the list according to its keys. */
  134.     sort_list_contents(list);
  135. }
  136.  
  137. sort_list_contents(list)
  138. List *list;
  139. {
  140.     int i;
  141.  
  142.     for (i = 0; i < MAXSORTKEYS; ++i) {
  143.         tmpsortkeys[i] = list->sortkeys[i];
  144.     }
  145.     sort_unit_vector(list->contents);
  146. }
  147.  
  148. add_unit_to_list(list, unit)
  149. List *list;
  150. Unit *unit;
  151. {
  152.     if (alive(unit)) {
  153.         list->contents = add_unit_to_vector(list->contents, unit, FALSE);
  154.         /* (should apply other inclusion criteria too?) */
  155.         ++list->numunits;
  156.     }
  157. }
  158.  
  159. set_list_scrollbar(list)
  160. List *list;
  161. {
  162.     int numvisunits = (list->window->portRect.bottom - list->window->portRect.top - sbarwid) / smallentryspacing;
  163.     /* Adjust scrollbars to fit the list size. */
  164.     SetCtlMax(list->hscrollbar, maxlistwidth);
  165.     SetCtlMax(list->vscrollbar, max(0, list->numunits - numvisunits));
  166. }
  167.  
  168. List *
  169. list_from_window(window)
  170. WindowPtr window;
  171. {
  172.     List *list;
  173.     
  174.     if (dside == NULL) return NULL;
  175.     for_all_lists(list) {
  176.         if (list->window == window) return list;
  177.     }
  178.     return NULL;
  179. }
  180.  
  181. draw_list(list)
  182. List *list;
  183. {
  184.     WindowPtr listwin = list->window;
  185.     Rect tmprect, cliprect;
  186.     RgnHandle tmprgn;
  187.  
  188.     tmprgn = NewRgn();
  189.     GetClip(tmprgn);
  190.     tmprect = listwin->portRect;
  191.     tmprect.right -= sbarwid;
  192.     BackPat(QD(white));
  193.     EraseRect(&tmprect);
  194.     /* Set up clipping for the contents of the list. */
  195.     cliprect = listwin->portRect;
  196.     cliprect.right -= sbarwid;
  197.     ClipRect(&cliprect);
  198.     TextSize(9);
  199.     draw_list_contents(list);
  200.     SetClip(tmprgn);
  201.     DisposeRgn(tmprgn);
  202. }
  203.     
  204. draw_list_contents(list)
  205. List *list;
  206. {
  207.     int line, numvisunits;
  208.     Rect tmprect;
  209.  
  210.     tmprect = list->window->portRect;
  211.     EraseRect(&tmprect);
  212.     entryspacing = (list->largeicons ? largeentryspacing : smallentryspacing);
  213.     /* Image is basically square, but add a bit of extra space on each side. */
  214.     imagecolw = entryspacing + 2;
  215.     /* Draw the selection and sorting as a sort of header. */
  216.     draw_list_headings(list);
  217.     /* Compute how many list elements are actually visible. */
  218.     numvisunits = (tmprect.bottom - tmprect.top - listtoph - sbarwid) / entryspacing;
  219.     numvisunits = min(numvisunits, list->numunits);
  220.     list->lastvisible = list->firstvisible + numvisunits - 1;
  221.     for (line = list->firstvisible; line <= list->lastvisible; ++line) {
  222.         draw_unit_list_entry(list, line, FALSE);
  223.     }
  224.     HiliteControl(list->vscrollbar, ((numvisunits < list->numunits) ? 0 : 255));
  225.     HiliteControl(list->hscrollbar, (((list->window->portRect.right - list->window->portRect.left - sbarwid) < maxlistwidth) ? 0 : 255));
  226.     /* (should do for hscroll also) */
  227. }
  228.  
  229. draw_list_headings(list)
  230. List *list;
  231. {
  232.     int x = 0, m;
  233.     Str255 tmpstr;
  234.     Rect cliprect;
  235.  
  236.     cliprect = list->window->portRect;
  237.     cliprect.right -= sbarwid;
  238.     ClipRect(&cliprect);
  239.     /* Draw a dividing line that crosses both fixed and scrolling fields. */
  240.     MoveTo(0, listtoph);
  241.     Line(list->window->portRect.right, 0);
  242.     /* (should underline sort keys with varying line heaviness) */
  243.     /* We have to do MoveTo everywhere because DrawString moves the pen. */
  244.     x += curactcolw;
  245.     MoveTo(x, 15);
  246.     DrawString("\ps/L");
  247.     x += imagecolw;
  248.     MoveTo(x, 15);
  249.     DrawString("\pName/Number");
  250.     /* Shift left by horiz scroll. */
  251.     x -= list->firstvisfield;
  252.     cliprect = list->window->portRect;
  253.     cliprect.right -= sbarwid;
  254.     cliprect.left = fixedfieldwidth;
  255.     ClipRect(&cliprect);
  256.     x += namecolw;
  257.     MoveTo(x, 15);
  258.     DrawString("\pType");
  259.     x += typecolw;
  260.     MoveTo(x, 15);
  261.     DrawString("\pSide");
  262.     x += sidecolw;
  263.     MoveTo(x, 15);
  264.     DrawString("\pHp");
  265.     x += hpcolw;
  266.     MoveTo(x, 15);
  267.     DrawString("\pAcp");
  268.     x += acpcolw;
  269.     MoveTo(x, 15);
  270.     DrawString("\pLoc");
  271.     x += poscolw;
  272.     for_all_material_types(m) {
  273.         MoveTo(x, 15);
  274.         c2p(m_type_name(m), tmpstr);
  275.         DrawString(tmpstr);
  276.         x += supcolw;
  277.     }
  278. }
  279.  
  280. /* This draws a one-line entry for the given unit. */
  281.  
  282. draw_unit_list_entry(list, n, clearfirst)
  283. List *list;
  284. int n, clearfirst;
  285. {
  286.     int u, m, x, y = (n - list->firstvisible) * entryspacing + listtoph;
  287.     int texty = y + 15;
  288.     Side *side2;
  289.     Rect entryrect, tmprect;
  290.     Unit *unit = list->contents->units[n].unit;
  291.     Rect cliprect;
  292.  
  293.     cliprect = list->window->portRect;
  294.     cliprect.right -= sbarwid;
  295.     ClipRect(&cliprect);
  296.  
  297.     SetRect(&entryrect, 0, y, list->window->portRect.right, y + entryspacing);
  298.     if (clearfirst) {
  299.         EraseRect(&entryrect);
  300.     }
  301.     if (unit == NULL || !alive(unit)) {
  302.         /* We need to recalculate the list contents. */
  303.         list->shouldreorg = TRUE;
  304.         return;
  305.     }
  306.     u = unit->type;
  307.     /* Draw whether the unit is awake or asleep. */
  308.     if (unit->plan && completed(unit)) {
  309.         SetRect(&tmprect, 0, y + entryspacing/2 - curactcolw/2,
  310.                 curactcolw, y + entryspacing/2 + curactcolw/2);
  311.         InsetRect(&tmprect, 2, 2);
  312.         /* (should draw the following analogously to map display) */
  313.         if (unit->plan->asleep) {
  314.             /* Leave rectangle blank. */
  315.         } else if (unit->plan->reserve) {
  316.             FillRect(&tmprect, QD(gray));
  317.         } else {
  318.             FillRect(&tmprect, QD(black));
  319.         }
  320.         FrameRect(&tmprect);
  321.     }
  322.     /* Draw an icon with side emblem for this unit. */
  323.     draw_unit_image(list->window, curactcolw + 2, y + 1,
  324.                     (list->largeicons ? 32 : 16), (list->largeicons ? 32 : 16),
  325.                     u, side_number(unit->side), !completed(unit));
  326.     /* Write the name or ordinal number. */
  327.     name_or_number(unit, spbuf);
  328.     spbuf[15] = '\0';  /* (should be clipping by pixels) */
  329.     x = curactcolw + imagecolw;
  330.     MoveTo(x, texty);
  331.     DrawText(spbuf, 0, strlen(spbuf));
  332.     /* Adjust according to the horizontal scroll. */
  333.     x -= list->firstvisfield;
  334.     cliprect = list->window->portRect;
  335.     cliprect.right -= sbarwid;
  336.     cliprect.left = fixedfieldwidth;
  337.     ClipRect(&cliprect);
  338.     /* Write the name of the unit's type. */
  339.     x += namecolw;
  340.     MoveTo(x, texty);
  341.     sprintf(spbuf, "%s", u_type_name(u));
  342.     spbuf[10] = '\0';
  343.     DrawText(spbuf, 0, strlen(spbuf));
  344.     /* Write the side of the unit. */
  345.     x += typecolw;
  346.     MoveTo(x, texty);
  347.     side2 = unit->side;
  348.     shortest_side_title(side2, spbuf);
  349.     spbuf[15] = '\0'; /* truncate long side names */
  350.     DrawText(spbuf, 0, strlen(spbuf));
  351.     /* Draw the current hit points of the unit. */
  352.     x += sidecolw;
  353.     if (side_sees_unit(dside, unit)) {
  354.         MoveTo(x, texty);
  355.         hp_desc(spbuf, unit, FALSE);
  356.         DrawText(spbuf, 0, strlen(spbuf));
  357.     }
  358.     x += hpcolw;
  359.     if (side_sees_unit(dside, unit)) {
  360.         MoveTo(x, texty);
  361.         acp_desc(spbuf, unit, FALSE);
  362.         if (strlen(spbuf) == 0) strcpy(spbuf, "-");
  363.         DrawText(spbuf, 0, strlen(spbuf));
  364.     }
  365.     /* Draw the location. */
  366.     x += acpcolw;
  367.     MoveTo(x, texty);
  368.     sprintf(spbuf, "%d,%d", unit->x, unit->y);
  369.     if (unit->z != 0) {
  370.         tprintf(spbuf, ",%d", unit->z);
  371.     }
  372.     DrawText(spbuf, 0, strlen(spbuf));
  373.     /* Draw the state of all the supplies. */
  374.     x += poscolw;
  375.     if (side_sees_unit(dside, unit)) {
  376.         for_all_material_types(m) {
  377.             MoveTo(x, texty);
  378.             sprintf(spbuf, "%d", unit->supply[m]);
  379.             DrawText(spbuf, 0, strlen(spbuf));
  380.             x += supcolw;
  381.         }
  382.     } else {
  383.         x += nummtypes * supcolw; /* actually not necessary since no more cols */
  384.     }
  385.     /* Fix the clipping. */
  386.     cliprect = list->window->portRect;
  387.     cliprect.right -= sbarwid;
  388.     ClipRect(&cliprect);
  389.     /* Highlight this entry if it was selected. */
  390.     if (list->contents->units[n].flag) {
  391.         InvertRect(&entryrect);
  392.     }
  393. }
  394.  
  395. grow_list(list, w, h)
  396. List *list;
  397. int w, h;
  398. {
  399.     WindowPtr listwin = list->window;
  400.  
  401.     EraseRect(&listwin->portRect);
  402.     SizeWindow(listwin, w, h, 1);
  403.     adjust_list_decor(list);
  404.     InvalRect(&listwin->portRect);
  405. }
  406.  
  407. /* Zooming works like a list view in the Finder - it calculates a "perfect" size,
  408.    showing as much as possible but with no wasted blank areas. */
  409.  
  410. zoom_list(list, part)
  411. List *list;
  412. short part;
  413. {
  414.     int maxh;
  415.     WindowPtr listwin = list->window;
  416.  
  417.     if (part == inZoomOut) {
  418.         entryspacing = (list->largeicons ? largeentryspacing : smallentryspacing);
  419.         maxh = listtoph + list->numunits * entryspacing + sbarwid;
  420.         set_standard_state(listwin, maxlistwidth, maxh);
  421.     }
  422.     EraseRect(&listwin->portRect);
  423.     ZoomWindow(listwin, part, true);
  424.     adjust_list_decor(list);
  425. }
  426.  
  427. adjust_list_decor(list)
  428. List *list;
  429. {
  430.     int w, h, spacing, lines;
  431.  
  432.     w = list->window->portRect.right - list->window->portRect.left;
  433.     h = list->window->portRect.bottom - list->window->portRect.top;
  434.     MoveControl(list->hscrollbar, (curactcolw+imagecolw+namecolw), h - sbarwid);
  435.     SizeControl(list->hscrollbar, w - (curactcolw+imagecolw+namecolw) - sbarwid + 1, sbarwid + 1);
  436.     MoveControl(list->vscrollbar, w - sbarwid, listtoph);
  437.     SizeControl(list->vscrollbar, sbarwid + 1, h - listtoph - sbarwid + 1);
  438.     spacing = (list->largeicons ? largeentryspacing : smallentryspacing);
  439.     lines = (h - listtoph - sbarwid) / spacing;
  440.     if (lines >= list->numunits) {
  441.         list->firstvisible = 0;
  442.     } else if ((list->firstvisible + lines) > list->numunits) {
  443.         list->firstvisible = list->numunits - 1 - lines;
  444.     }
  445.     SetCtlValue(list->vscrollbar, list->firstvisible);
  446. }
  447.  
  448. List *curlist = NULL;
  449.  
  450. pascal void
  451. list_vscroll_proc(control, code)
  452. ControlHandle control;
  453. short code;
  454. {
  455.     int curvalue, minvalue, maxvalue, pagesize, dir, jump;
  456.  
  457.     if (curlist == NULL) return;
  458.  
  459.     curvalue = GetCtlValue(control);
  460.     minvalue = GetCtlMin(control);
  461.     maxvalue = GetCtlMax(control);
  462.     pagesize = curlist->lastvisible - curlist->firstvisible + 1;
  463.     switch (code) {
  464.         case inPageDown:
  465.             jump = max(1, pagesize - 1);
  466.             break;
  467.         case inDownButton:
  468.             jump = 1;
  469.             break;
  470.         case inPageUp:
  471.             jump = min(-1, - (pagesize - 1));
  472.             break;
  473.         case inUpButton:
  474.             jump = -1;
  475.             break;
  476.         default:
  477.             jump = 0;
  478.             break;
  479.     }
  480.     curvalue = max(min(curvalue + jump, maxvalue), minvalue);
  481.     curlist->firstvisible = curvalue;
  482.     curlist->lastvisible = min(curlist->numunits, curlist->firstvisible + pagesize) - 1;
  483.     SetCtlValue(control, curvalue);
  484.     curlist = NULL;
  485. }
  486.  
  487. pascal void
  488. list_hscroll_proc(control, code)
  489. ControlHandle control;
  490. short code;
  491. {
  492.     int curvalue, minvalue, maxvalue, pagesize, dir, jump;
  493.  
  494.     if (curlist == NULL) return;
  495.  
  496.     curvalue = GetCtlValue(control);
  497.     minvalue = GetCtlMin(control);
  498.     maxvalue = GetCtlMax(control);
  499.     pagesize = curlist->lastvisfield - curlist->firstvisfield;
  500.     switch (code) {
  501.         case inPageDown:
  502.             jump = pagesize - 10;
  503.             break;
  504.         case inDownButton:
  505.             jump = 10;
  506.             break;
  507.         case inPageUp:
  508.             jump = - (pagesize - 10);
  509.             break;
  510.         case inUpButton:
  511.             jump = -10;
  512.             break;
  513.         default:
  514.             jump = 0;
  515.             break;
  516.     }
  517.     curvalue = max(min(curvalue + jump, maxvalue), minvalue);
  518.     curlist->firstvisfield = curvalue;
  519.     curlist->lastvisfield = curlist->firstvisfield + pagesize;
  520.     SetCtlValue(control, curvalue);
  521.     curlist = NULL;
  522. }
  523.  
  524. /* Handle a mouse down in the list.  Grafport already set, mouse coords are local. */
  525.  
  526. /* (mouse downs should select/deselect list elements) */
  527.  
  528. do_mouse_down_list(list, mouse, mods)
  529. List *list;
  530. Point mouse;
  531. int mods;
  532. {
  533.     ControlHandle control;
  534.     short part, value;
  535.     int n, tmp;
  536.     WindowPtr window = list->window;
  537.  
  538.     part = FindControl(mouse, window, &control);
  539.     if (control == list->vscrollbar) {
  540.         switch (part) {
  541.             case inThumb:
  542.                 part = TrackControl(control, mouse, NULL);
  543.                 list->firstvisible = GetCtlValue(control);
  544.                 force_update(window);
  545.                 break;
  546.             default:
  547.                 curlist = list;
  548.                 part = TrackControl(control, mouse, (ProcPtr) list_vscroll_proc);
  549.                 force_update(window);
  550.                 break;
  551.         }
  552.     } else if (control == list->hscrollbar) {
  553.         switch (part) {
  554.             case inThumb:
  555.                 part = TrackControl(control, mouse, NULL);
  556.                 list->firstvisfield = GetCtlValue(control);
  557.                 force_update(window);
  558.                 break;
  559.             default:
  560.                 curlist = list;
  561.                 part = TrackControl(control, mouse, (ProcPtr) list_hscroll_proc);
  562.                 force_update(window);
  563.                 break;
  564.         }
  565.     } else {
  566.         if (mouse.v < listtoph) {
  567.             if (between(curactcolw, mouse.h, curactcolw + imagecolw)) {
  568.                 toggle_list_large_icons(list);
  569.             }
  570.             /* do others eventually */
  571.         } else {
  572.             /* Figure out the selected unit. */
  573.             n = (mouse.v - listtoph) / entryspacing + list->firstvisible;
  574.             tmp = list->contents->units[n].flag;
  575.             clear_selections(list);
  576.             list->contents->units[n].flag = !tmp;
  577.             redraw_unit_list_entry(list, n);
  578.         }
  579.     }
  580. }
  581.  
  582. set_list_sorting(list, newkey, mi)
  583. List *list;
  584. enum sortkeys newkey;
  585. int mi;
  586. {
  587.     int i;
  588.     
  589.     if (newkey != list->sortkeys[0]) {
  590.         /* Push all the existing sortkeys back - this way they'll can be
  591.            used as tiebreakers for the new sort key. */
  592.         for (i = MAXSORTKEYS - 1; i > 0; --i) {
  593.             list->sortkeys[i] = list->sortkeys[i - 1];
  594.         }
  595.         /* Add the new one onto the front. */
  596.         list->sortkeys[0] = newkey;
  597.         sort_list_contents(list);
  598.         force_update(list->window);
  599.         /* Record the menu item so it can get a checkmark during menu adjust. */
  600.         list->mainsortmi = mi;
  601.     }
  602. }
  603.  
  604. toggle_list_large_icons(list)
  605. List *list;
  606. {
  607.     list->largeicons = !list->largeicons;
  608.     force_update(list->window);
  609. }
  610.  
  611. update_unit_in_lists(unit)
  612. Unit *unit;
  613. {
  614.     int line;
  615.     List *list;
  616.  
  617.     for_all_lists(list) {
  618.         if ((line = unit_position_in_list(list, unit)) >= 0) {
  619.             if (between(list->firstvisible, line, list->lastvisible)) {
  620.                 redraw_unit_list_entry(list, line);
  621.             }
  622.         } else {
  623. /*            add_unit_to_list(list, unit); */
  624.             organize_list_contents(list);
  625.             force_update(list->window);
  626.         }
  627.     }
  628. }
  629.  
  630. unit_position_in_list(list, unit)
  631. List *list;
  632. Unit *unit;
  633. {
  634.     int i;
  635.     
  636.     for (i = 0; i < list->numunits; ++i) {
  637.         if (unit == list->contents->units[i].unit) return i;
  638.     }
  639.     return (-1);
  640. }
  641.  
  642. redraw_unit_list_entry(list, n)
  643. List *list;
  644. int n;
  645. {
  646.     WindowPtr listwin;
  647.     Rect cliprect;
  648.     GrafPtr oldport;
  649.     RgnHandle tmprgn;
  650.  
  651.     if (!active_display(dside) || list == NULL) return;
  652.  
  653.     listwin = list->window;
  654.      GetPort(&oldport);
  655.     SetPort(listwin);
  656.     tmprgn = NewRgn();
  657.     GetClip(tmprgn);
  658.     /* Set up clipping for the contents of the list. */
  659.     cliprect = listwin->portRect;
  660.     cliprect.right -= sbarwid;
  661.     ClipRect(&cliprect);
  662.     TextSize(9);
  663.     draw_unit_list_entry(list, n, TRUE);
  664.     SetClip(tmprgn);
  665.     DisposeRgn(tmprgn);
  666.     SetPort(oldport);
  667. }
  668.  
  669. clear_selections(list)
  670. List *list;
  671. {
  672.     int i;
  673.     
  674.     for (i = 0; i < list->numunits; ++i) {
  675.         if (list->contents->units[i].flag) {
  676.             list->contents->units[i].flag = FALSE;
  677.             redraw_unit_list_entry(list, i);
  678.         }
  679.     }
  680. }
  681.  
  682. Unit *
  683. selected_unit_in_list(list)
  684. List *list;
  685. {
  686.     int i;
  687.     
  688.     for (i = 0; i < list->numunits; ++i) {
  689.         if (list->contents->units[i].flag) return list->contents->units[i].unit;
  690.     }
  691.     return NULL;
  692. }
  693.  
  694. /* This finds a good map to scroll over to look at a unit mentioned in the list. */
  695.  
  696. scroll_to_selected_unit_in_list(list)
  697. List *list;
  698. {
  699.     Unit *unit;
  700.     Map *map, *bestmap;
  701.     
  702.     if ((unit = selected_unit_in_list(list)) != NULL
  703.         && inside_area(unit->x, unit->y)) {
  704.         /* Find the best map to scroll over to the unit. */
  705.         bestmap = maplist;
  706.         for_all_maps(map) {
  707.             if (map->power > bestmap->power
  708.                 || (map->power == bestmap->power
  709.                     && in_middle(map, unit->x, unit->y)
  710.                      && !in_middle(bestmap, unit->x, unit->y))) {
  711.                 bestmap = map;
  712.             }
  713.         }
  714.         /* We found a map, now make it show the unit. */
  715.         if (bestmap != NULL) {
  716.             if (!in_middle(bestmap, unit->x, unit->y)) {
  717.                 scroll_to_unit(bestmap, unit);
  718.             }
  719.             SelectWindow(bestmap->window);
  720.             adjust_menus(); 
  721.         }
  722.     }
  723. }
  724.  
  725. activate_list(list, activate)
  726. List *list;
  727. int activate;
  728. {
  729.     Rect growRect;
  730.  
  731.     if (activate) {
  732.         HiliteControl(list->vscrollbar, 0);
  733.         HiliteControl(list->hscrollbar, 0);
  734. #if 0
  735.         /* the controls must be redrawn on activation: */
  736.         (*(list->vscrollbar))->contrlVis = 255;
  737.         (*(list->hscrollbar))->contrlVis = 255;
  738.         InvalRect(&(*(list->vscrollbar))->contrlRect);
  739.         InvalRect(&(*(list->hscrollbar))->contrlRect);
  740. #endif
  741.         /* The growbox needs to be redrawn on activation. */
  742.         growRect = list->window->portRect;
  743.         /* adjust for the scrollbars */
  744.         growRect.top = growRect.bottom - sbarwid;
  745.         growRect.left = growRect.right - sbarwid;
  746.         InvalRect(&growRect);
  747.     } else {
  748.         /* The scrollbars must be hidden on deactivation. */
  749.         HiliteControl(list->vscrollbar, 255);
  750.         HiliteControl(list->hscrollbar, 255);
  751. /*        HideControl(list->vscrollbar);
  752.         HideControl(list->hscrollbar); */
  753.         /* The growbox should be changed immediately on deactivation. */
  754.         DrawGrowIcon(list->window);
  755.     }
  756. }
  757.  
  758. print_list(list)
  759. List *list;
  760. {
  761. /*    TPPrPort printport;
  762.     extern THPrint printrecordhandle;
  763.  
  764.     printport = PrOpenDoc(printrecordhandle, nil, nil);
  765.     PrCloseDoc(printport); */
  766. }
  767.  
  768. /* Remove and destroy the list object. */
  769.  
  770. destroy_list(list)
  771. List *list;
  772. {
  773.     List *list2;
  774.     
  775.     if (listlist == list) {
  776.         listlist = list->next;
  777.     } else {
  778.         for_all_lists(list2) {
  779.             if (list2->next == list) {
  780.                 list2->next = list->next;
  781.             }
  782.         }
  783.     }
  784.     /* (should destroy substructs) */
  785.     free(list);
  786. }
  787.